package xx.services.entity.rest;

import java.sql.Date;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.sql.RowSet;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;

import xx.entity.bas.Attach;
import xx.entity.bas.Category;
import xx.entity.bas.CategoryLink;
import xx.entity.bas.Comment;
import xx.entity.bas.Entity;
import xx.entity.bas.EntityExt;
import xx.entity.bas.EntityExtDefined;
import xx.entity.bas.Mood;
import xx.entity.bas.MoodLink;
import xx.entity.bas.Picture;
import xx.entity.bas.ProjectPay;
import xx.entity.bas.Relation;
import xx.entity.bas.Sacrifice;
import xx.entity.bas.SacrificeLink;
import xx.entity.bas.dao.EntityDao;
import xx.services.Passport;
import xx.services.entity.inter.IEntityInterface;
import xx.services.util.Constants;
import xx.util.Arr;
import xx.util.string.Format;

/**
 * 实体服务接口<br>
 * 
 * @Path (Constants.RESTFUL_ROOT_PATH + "/{entity}") {entity}根据不用的类型不一样，如产品应该为product，文章应用为article
 * @author dengjinye,2010-12-18 $LastChangedDate$ $Author$
 */
public class EntityFactoryRest extends Passport implements IEntityInterface
{
    /** 实体对应的分类对象 */
    protected final Category category = new Category(qr, owner);

    /** 当前实体对象，必须调用initEntity方法来初始化 */
    protected Entity entity;

    public EntityFactoryRest(@Context
    HttpServletRequest request)
    {
        super(request);
    }

    /**
     * 初始化实体
     * 
     * @param entity
     */
    protected void initEntity(Entity entity)
    {
        this.entity = entity;
        this.category.setSign(this.entity.getSign());
    }

    /**
     * 添加与实体{entity_id}关联的附件。<br>
     * 注：附件名称与描述通过fileId从Xfile中获取。
     * 
     * @POST
     * @Path ("/{entity_id}/attach")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @param fileId
     *            -@FormParam("file_id") 文件ID，关联Xfile
     * @param description
     *            -@FormParam("description") 附件描述
     * @return 添加的附件实体
     * @author dengjinye,2010-10-29
     */
    @POST
    @Path("/{entity_id}/attach")
    public String addAttach(@PathParam("entity_id")
    long entityId, @FormParam("file_id")
    long fileId, @FormParam("description")
    String description)
    {
        try
        {
            EntityDao ed = new EntityDao(qr, owner, entityId);
            // 新增一个附件
            Attach attach = ed.addAttach(fileId, description);

            addUrlLog(String.valueOf(attach.getAttachId()),String.valueOf(attach.getEntityId()));

            return ok(attach);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 增加根分类
     * 
     * @POST
     * @Path ("/category")
     * @param name
     *            -@FormParam("name") 分类名称
     * @param description
     *            -@FormParam("description") 分类描述
     * @return 新增的分类实体
     */
    @POST
    @Path("/category")
    public String addCategoryRoot(@FormParam("name")
    String name, @FormParam("keyword")
    String keyword, @FormParam("description")
    String description)
    {
        try
        {
            if (Format.isEmpty(name))
            {
                return null;
            }

            category.setParentId(0).setName(name);
            category.setKeyword(keyword);
            if (!Format.isEmpty(description))
            {
                category.setDescription(description);
            }
            long insertId = category.insert();

            // 将父category的横向扩展属性定义值复制给新的cagegory
            EntityExtDefined entityExtDefined = new EntityExtDefined(qr, owner);
            entityExtDefined.setCategoryId(Integer.valueOf("-" + category.getSign())).load();
            entityExtDefined.setCategoryId(insertId).insert();

            return ok(category);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 添加对实体{entity_id}的评论。<br>
     * 
     * @POST
     * @Path ("/{entity_id}/comment")
     * @param entityId
     *            实体id
     * @param title
     *            标题
     * @param content
     *            内容
     * @return
     * @author dengjinye,2011-1-25
     */
    @POST
    @Path("/{entity_id}/comment")
    public String addComment(@PathParam("entity_id")
    long entityId, @FormParam("title")
    String title, @FormParam("content")
    String content)
    {
        try
        {
            Comment comment = new Comment(qr, owner);
            comment.setEntityId(entityId).setTitle(title).setContent(content).setIp(ip);
            comment.insert();
            return ok(comment);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 添加与实体{entity_id}关联的心情描述。<br>
     * 注：每个实体最多只能添加一次心情描述，心情描述ID从心情表(mood)中取出，放到实体与心情的关联表中
     * 
     * @POST
     * @Path ("/{entity_id}/mood")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 添加的mood列表
     * @author dengjinye,2010-10-29
     */
    @POST
    @Path("/{entity_id}/mood")
    public String addMood(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            int count = entity.setEntityId(entityId).getMoodCount();
            if (count > 0)
            {
                return null;
            }

            Mood mood = new Mood(qr, owner);
            RowSet rs = mood.getAllMoodId();
            while (rs.next())
            {
                long moodId = rs.getLong("mood_id");
                MoodLink newMoodLink = new MoodLink(qr, owner);
                newMoodLink.setEntityId(entityId).setMoodId(moodId);
                newMoodLink.insert();
            }
            return ok(rs);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 添加与实体{entity_id}关联的图片。<br>
     * 注：图片名称与描述通过fileId从Xfile中获取。
     * 
     * @POST
     * @Path ("/{entity_id}/picture")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @param fileId
     *            -@FormParam("file_id") 文件ID，关联Xfile
     * @param description
     *            -@FormParam("description") 附件描述
     * @return 添加的Xfile实体
     * @author dengjinye,2010-10-29
     */
    @POST
    @Path("/{entity_id}/picture")
    public String addPicture(@PathParam("entity_id")
    long entityId, @FormParam("file_id")
    long fileId, @FormParam("description")
    String description)
    {
        try
        {
            EntityDao ed = new EntityDao(qr, owner, entityId);
            // 新建picture
            Picture picture = ed.addPicture(fileId, description);

            return ok(picture);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 增加与实体{entity_id}关联的实体。
     * 
     * @POST
     * @Path ("/{entity_id}/relation/{relation_entity_id}")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @param entityRelationId
     *            -@PathParam("relation_entity_id") 需要关联的实体ID集，多个ID用“_”隔开
     * @return 实体对应的关联实体列表
     */
    @POST
    @Path("/{entity_id}/relation/{relation_entity_id}")
    public String addRelation(@PathParam("entity_id")
    long entityId, @PathParam("relation_entity_id")
    String entityRelationId)
    {
        try
        {
            long[] entityRelationIdArr = Format.strTolongArray(entityRelationId, "_");
            for (long id : entityRelationIdArr)
            {
                if (entityId == id) // 过虑掉关联自己
                    continue;
                Relation relation = new Relation(qr, owner);
                relation.setEntityId(entityId).setEntityRelationId(id);
                relation.insert();
            }
            return ok(true);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 添加与实体{entity_id}关联的祭拜。<br>
     * 注：每个实体最多只能添加一次祭拜，祭拜ID从祭拜表(sacrifice)中取出，放到实体与祭拜的关联表中
     * 
     * @POST
     * @Path ("/{entity_id}/sacrifice")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 添加的sacrifice列表
     * @author dengjinye,2010-10-29
     */
    @POST
    @Path("/{entity_id}/sacrifice")
    public String addSacrifice(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            int count = entity.setEntityId(entityId).getSacrificeCount();
            if (count > 0)
            {
                return null;
            }

            Sacrifice sacrifice = new Sacrifice(qr, owner);
            RowSet rs = sacrifice.getAllSacrificeId();
            while (rs.next())
            {
                long sacrificeId = rs.getLong("sacrifice_id");
                SacrificeLink sl = new SacrificeLink(qr, owner);
                sl.setEntityId(entityId).setSacrificeId(sacrificeId);
                sl.insert();
            }
            return ok(rs);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 对实体的支持率
     * 
     * @POST
     * @Path ("/{entity_id}/agree")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @return 最新支持率
     */
    @POST
    @Path("/{entity_id}/agree")
    public String agree(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId).total(Entity.AGREE, 1);
            return ok(true);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 1）此接口为受保护接口；2）删除实体{entity_id}，同时也会删除与之关联的实体数据。
     * 
     * @DELETE
     * @Path ("/{entity_id}")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID，多个实体ID用“_”连接起来
     * @param categoryId
     *            实体与在的分组ID
     * @return String 下午09:27:05
     * @author dengjinye
     */
    @DELETE
    @Path("/{entity_id}")
    public String deleteEntity(@PathParam("entity_id")
    String entityId, @QueryParam("category_id")
    long categoryId)
    {
        try
        {
            long[] eIds = Format.strTolongArray(entityId, "_");

            // 判断是否有锁定的entity
            boolean isLock = checkLock(eIds);
            if (isLock)
            {
                return error("删除信息中存在被锁定数据！");
            }

            for (long eId : eIds)
            {
                CategoryLink cl = new CategoryLink(qr, owner);
                cl.setCategoryId(categoryId).setEntityId(eId).delete();
                // entity.setEntityId(eId).delete();
                addUrlLog(String.valueOf(eId),String.valueOf(eId));
            }
            return ok(true);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 检验实体是否被锁定
     * 
     * @param entityIds
     * @return true: 被锁定 false：没有被锁定
     * @throws SQLException
     * @author dengjinye 2013-6-4
     */
    private boolean checkLock(long... entityIds) throws SQLException
    {
        boolean isLock = false;
        for (long id : entityIds)
        {
            isLock = entity.setEntityId(id).checkLock();
            if (isLock)
            {
                return true;
            }
        }
        return isLock;
    }

    /**
     * 删除与实体{entity_id}关联的实体。
     * 
     * @DELETE
     * @Path ("/{entity_id}/relation/{relation_entity_id}")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @param entityRelationId
     *            -@PathParam("relation_entity_id") 需要关联的实体ID集，多个ID用“_”隔开
     * @return 删除成功的关联实体ID
     */
    @DELETE
    @Path("/{entity_id}/relation/{relation_entity_id}")
    public String deleteRelation(@PathParam("entity_id")
    long entityId, @PathParam("relation_entity_id")
    String entityRelationId)
    {
        try
        {
            Relation relation = new Relation(qr, owner);

            // 判断是否有锁定的entity
            boolean isLock = checkLock(entityId);
            if (isLock)
            {
                return error("删除信息中存在被锁定数据！");
            }

            relation.setEntityId(entityId);
            if (entityRelationId != null && !"".equals(entityRelationId))
            {
                long[] entityRelationArr = Arr.toLongArray(entityRelationId, "_");
                relation.delete(entityRelationArr);
            }
            else
            {
                relation.deleteByEntityId();
            }
            return ok(true);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 对实体的反对率
     * 
     * @POST
     * @Path ("/{entity_id}/differ")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @return 最新反对率
     */
    @POST
    @Path("/{entity_id}/differ")
    public String differ(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId).total(Entity.DIFFER, 1);
            return ok(true);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 描述：1）此接口为公共接口；2）获取与实体{entity_id}关联的附件列表。
     * 
     * @GET
     * @Path ("/{entity_id}/attach")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 实体对应的附件列表
     * @author dengjinye,2010-10-29
     */
    @GET
    @Path("/{entity_id}/attach")
    public String getAttachList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            List<Attach> rs = entity.setEntityId(entityId).getAttachList(pageSize, pageNo, condition, orderField);
            Map<String, Object> map = new HashMap<String, Object>();
            if (isTotal)
            {
                map.put(Constants.TOTAL, entity.getAttachCount(condition));
            }
            return ok(rs, map);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取实体对应的根分类列表
     * 
     * @GET
     * @Path ("/category")
     * @return Category分类列表
     */
    @GET
    @Path("/category")
    public String getCategoryRoot()
    {
        try
        {
            RowSet rs = category.setCategoryId(0).getChildren();
            return ok(rs);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 描述：获取关联实体评论列表，按日期排序，最新的排在最前面
     * 
     * @GET
     * @Path ("/{entity_id}/comment")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 实体对应的评论列表
     */
    @GET
    @Path("/{entity_id}/comment")
    public String getCommentList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            Entity entity = new Entity(qr, owner);
            entity.setEntityId(entityId);
            RowSet rs = entity.setEntityId(entityId).getCommentRowSet(pageSize, pageNo, condition, orderField);
            Map<String, Object> map = new HashMap<String, Object>();
            if (isTotal)
            {
                map.put(Constants.TOTAL, entity.getCommentCount(condition));
            }
            return ok(rs, map);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取实体{entity_id}的详细信息等(包含关联实体数据)。<br>
     * 注：如果不是从管理后台进入，需要对实体的访问量(total)加1
     * 
     * @GET
     * @Path ("/{entity_id}")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @param jsonkeys
     *            -@QueryParam("jsonkeys") 需要返回关联的数据对应用的JSONkey<br>
     *            多个JSONkey用逗号“,”隔开，Jsonkey从实体API中获取。<br>
     * @return Entity实体
     * @author dengjinye
     */
    @GET
    @Path("/{entity_id}")
    public String getEntity(@PathParam("entity_id")
    long entityId, @QueryParam("jsonkeys")
    String jsonkeys)
    {
        try
        {
            entity.setEntityId(entityId).load(fields);
            if (jsonkeys != null && !"".equals(jsonkeys.trim()))
            {
                String[] jsonkey = jsonkeys.split(",");
                for (String key : jsonkey)
                {
                    entity.addJsonKey(key.trim());
                }
            }
            return ok(entity);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取与实体{entity_id}关联的心情。
     * 
     * @GET
     * @Path ("/{entity_id}/mood")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 实体对应的心情列表
     * @author dengjinye,2010-10-29
     */
    @GET
    @Path("/{entity_id}/mood")
    public String getMoodList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            RowSet rs = entity.getMoodRowSet();
            return ok(rs);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取与实体{entity_id}关联的图片集。
     * 
     * @GET
     * @Path ("/{entity_id}/picture")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @return 实体对应的图片列表
     * @author dengjinye,2010-10-29
     */
    @GET
    @Path("/{entity_id}/picture")
    public String getPictureList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            List<Picture> list = entity.setEntityId(entityId).getPictureList(pageSize, pageNo, condition, orderField);
            Map<String, Object> map = new HashMap<String, Object>();
            if (isTotal)
            {
                map.put(Constants.TOTAL, entity.getPictureCount(condition));
            }
            return ok(list, map);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取与实体{entity_id}关联的实体。
     * 
     * @GET
     * @Path ("/{entity_id}/relation")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @return 实体对应的关联实体列表
     */
    @GET
    @Path("/{entity_id}/relation")
    public String getRelation(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            List<Entity> rs = entity.setEntityId(entityId).getRelationList(pageSize, pageNo, condition, orderField);

            // 如果是获取第一页的数据，则同时返回总数
            Map<String, Object> map = new HashMap<String, Object>();
            if (isTotal)
            {
                map.put(Constants.TOTAL, entity.getRelationCount(condition));
            }
            return ok(rs, map);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 获取与实体{entity_id}关联的祭拜。
     * 
     * @GET
     * @Path ("/{entity_id}/sacrifice")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @return 实体对应的祭拜列表
     * @author dengjinye,2010-10-29
     */
    @GET
    @Path("/{entity_id}/sacrifice")
    public String getSacrificeList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            RowSet rs = entity.getSacrificeRowSet();
            return ok(rs);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 修改实体{entity_id}的名称等。
     * 
     * @PUT
     * @Path ("/{entity_id}")
     * @param entityId
     *            -@PathParam("entity_id") 指定实体ID
     * @param title
     *            -@FormParam("title") 实体标题
     * @param content
     *            -@FormParam("content") 实体内容
     * @param url
     *            -@FormParam("url") 指定URL地址
     * @param fileId
     *            -@FormParam("file_id") 关联实体ID
     * @param tags
     *            -@FormParam("tags") 实体tag标签，多个tag标签用空格“ ”隔开
     * @param value
     *            -@FormParam("value") 实体的扩展属性值
     * @return 修改后的实体
     * @author dengjinye,2010-12-6
     */
    @PUT
    @Path("/{entity_id}")
    public String updateEntity(@PathParam("entity_id")
    long entityId, @FormParam("title")
    String title, @FormParam("content")
    String content, @FormParam("url")
    String url, @FormParam("file_id")
    long fileId, @FormParam("tags")
    String tags, MultivaluedMap<String, String> formParams)
    {
        try
        {
            // 判断是否有锁定的entity
            boolean lockFlag = checkLock(entityId);
            String islock = formParams.getFirst(Entity.ISLOCK);
            if (lockFlag && (islock != null && "1".equals(islock.trim())))
            {
                return error("数据已经被锁定！");
            }

            entity.setEntityId(entityId);
            StringBuilder updateColumn = new StringBuilder();

            if (Format.noEmpty(title))
            {
                updateColumn.append(Entity.TITLE);
                entity.setTitle(title);
            }
            if (islock != null && !"".equals(islock.trim()))
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.ISLOCK);
                entity.setIslock(Integer.valueOf(islock));
            }
            String ontop = formParams.getFirst(Entity.ONTOP);
            if (ontop != null && !"".equals(ontop.trim()))
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.ONTOP);
                entity.setOntop(Integer.valueOf(ontop));
            }
            if (content != null && !"".equals(content.trim()))
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.CONTENT);
                entity.setContent(content);
            }
            if (url != null && !"".equals(url.trim()))
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.URL);
                entity.setUrl(url);
            }
            if (fileId > 0)
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.FILE_ID);
                entity.setFileId(fileId);
            }
            if (Format.noEmpty(tags))
            {
                if (updateColumn.length() > 0)
                    updateColumn.append(",");
                updateColumn.append(Entity.TAGS);
                entity.setTags(tags);
            }

            if (updateColumn.length() == 0)
                return ok(false);

            entity.update(updateColumn.toString());

            // 插入横向扩展属性 add by dengjinye 20130521
            long categoryId = entity.getCategoryIdByEntityId(entityId);
            EntityExtDefined entityExtDefined = new EntityExtDefined(qr, owner);
            entityExtDefined.setCategoryId(categoryId).load(EntityExtDefined.USED_FIELDS);
            String[] usedFieldsArr = entityExtDefined.getUsedFields().split(",");
            EntityExt ext = new EntityExt(qr, owner);
            for (String field : usedFieldsArr)
            {
                String value = formParams.getFirst(field);
                ext.setValue(field, value);
                entity.addOtherValue(field, value);
            }
            ext.setEntityId(entityId);
            ext.update(usedFieldsArr);

            // 更新扩展属性 add by dengjinye 20130509
            String v = formParams.getFirst("value");
            if (v != null && !"".equals(v))
            {
                DatumRest dr = new DatumRest(request);
                dr.updateDatum(entityId, v);
            }

            addUrlLog(String.valueOf(entityId),String.valueOf(entityId));
            return ok(entity);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 复制实体
     * 
     * @POST
     * @Path ("/{category_id}/{entity_id}/copyto/{to_category_id}")
     * @param categoryId
     * @param entityId
     * @param toCategoryId
     * @return
     */
    @POST
    @Path("/{category_id}/{entity_id}/copyto/{to_category_id}")
    public String copyEntity(@PathParam("category_id")
    long categoryId, @PathParam("entity_id")
    String entityId, @PathParam("to_category_id")
    String toCategoryId)
    {
        try
        {
            long[] entityIdArr = Format.strTolongArray(entityId, "_");
            int count = 0;
            long[] toCategoryIds = Format.strTolongArray(toCategoryId, "_");
            for (long toId : toCategoryIds)
            {
                for (long id : entityIdArr)
                {
                    CategoryLink cl = new CategoryLink(qr, owner);
                    cl.setEntityId(id).setCategoryId(toId).insert();
                    count++;
                }
            }
            return ok(count);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 移动实体
     * 
     * @PUT
     * @Path ("/{category_id}/{entity_id}/moveto/{to_category_id}")
     * @param categoryId
     *            原分组id
     * @param entityId
     *            多个实体间用"_"间隔
     * @param toCategoryId
     *            目标分组id
     * @return
     */
    @PUT
    @Path("/{category_id}/{entity_id}/moveto/{to_category_id}")
    public String moveEntity(@PathParam("category_id")
    long categoryId, @PathParam("entity_id")
    String entityId, @PathParam("to_category_id")
    long toCategoryId)
    {
        try
        {
            long[] entityIdArr = Format.strTolongArray(entityId, "_");
            int count = 0;
            for (long id : entityIdArr)
            {
                CategoryLink cl = new CategoryLink(qr, owner);
                cl.setEntityId(id).setCategoryId(toCategoryId).insert();
                CategoryLink cll = new CategoryLink(qr, owner);
                cll.setEntityId(id).setCategoryId(categoryId).delete();
                count++;
            }
            return ok(count);
        }
        catch (SQLException e)
        {
            return error(e);
        }
    }

    /**
     * 获取对实体的支付明细
     * 
     * @POST
     * @Path ("/{entity_id}/pay")
     * @param entityId
     *            -@PathParam("entity_id") 实体ID
     * @return 支付明细
     * @author dengjinye,2013-5-29
     */
    @GET
    @Path("/{entity_id}/pay")
    public String getPayList(@PathParam("entity_id")
    long entityId)
    {
        try
        {
            entity.setEntityId(entityId);
            List<ProjectPay> rs = entity.getPayList(pageSize, pageNo, condition, orderField);
            return ok(rs);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }

    /**
     * 新增实体的支付明细
     * 
     * @POST
     * @Path ("/{entity_id}/pay")
     * @param entityId
     *            实体ID
     * @param paydate
     *            支付日期
     * @param payprice
     *            支付金额
     * @param ord
     *            第N次支付
     * @return
     * @author dengjinye,2013-5-29
     */
    @POST
    @Path("/{entity_id}/pay")
    public String addPay(@PathParam("entity_id")
    long entityId, @FormParam("paydate")
    String paydate, @FormParam("payprice")
    String payprice, @FormParam("ord")
    String ord)
    {
        try
        {
            ProjectPay projectPay = new ProjectPay(qr, owner);
            projectPay.setEntityId(entityId).setPaydate(Date.valueOf(paydate)).setPayprice(Double.valueOf(payprice)).setOrd(Integer.valueOf(ord)).insert();

            addUrlLog(String.valueOf(projectPay.getPayId()),String.valueOf(projectPay.getEntityId()));
            return ok(projectPay);
        }
        catch (Exception e)
        {
            return error(e);
        }
    }
}
